// Decompiled on 周六 2月 22 19:31:49 CST 2025 with Zomboid Decompiler v0.1.3 using Vineflower.
package zombie.core.physics;

import java.util.ArrayList;
import java.util.HashMap;
import org.joml.Quaternionf;
import org.joml.Vector3f;
import zombie.characters.IsoPlayer;
import zombie.core.profiling.PerformanceProfileProbe;
import zombie.core.textures.TextureDraw;
import zombie.iso.IsoChunkMap;
import zombie.iso.IsoMovingObject;
import zombie.iso.IsoWorld;
import zombie.network.GameClient;
import zombie.network.GameServer;
import zombie.network.MPStatistic;
import zombie.vehicles.BaseVehicle;
import zombie.vehicles.VehicleManager;

public final class WorldSimulation {
    public static WorldSimulation instance = new WorldSimulation();
    public static final boolean LEVEL_ZERO_ONLY = true;
    public HashMap<Integer, IsoMovingObject> physicsObjectMap = new HashMap();
    public boolean created = false;
    public float offsetX = 0.0F;
    public float offsetY = 0.0F;
    public long time;
    private final ArrayList<BaseVehicle> collideVehicles = new ArrayList(4);
    private final Vector3f tempVector3f = new Vector3f();
    private final Vector3f tempVector3f_2 = new Vector3f();
    private final Transform tempTransform = new Transform();
    private final Quaternionf javaxQuat4f = new Quaternionf();
    private final float[] ff = new float[8192];
    private final float[] wheelSteer = new float[4];
    private final float[] wheelRotation = new float[4];
    private final float[] wheelSkidInfo = new float[4];
    private final float[] wheelSuspensionLength = new float[4];

    public void create() {
        if (!this.created) {
            this.offsetX = (float)(IsoWorld.instance.MetaGrid.getMinX() * 300);
            this.offsetY = (float)(IsoWorld.instance.MetaGrid.getMinY() * 300);
            this.time = zombie.GameTime.getServerTimeMills();
            IsoChunkMap isoChunkMap = IsoWorld.instance.CurrentCell.ChunkMap[0];
            Bullet.initWorld((int)this.offsetX, (int)this.offsetY, isoChunkMap.getWorldXMin(), isoChunkMap.getWorldYMin(), IsoChunkMap.ChunkGridWidth);

            for (int _int = 0; _int < 4; _int++) {
                this.wheelSteer[_int] = 0.0F;
                this.wheelRotation[_int] = 0.0F;
                this.wheelSkidInfo[_int] = 0.0F;
                this.wheelSuspensionLength[_int] = 0.0F;
            }

            this.created = true;
        }
    }

    public void destroy() {
        Bullet.destroyWorld();
    }

    private void updatePhysic(float _float) {
        MPStatistic.getInstance().Bullet.Start();
        Bullet.stepSimulation(_float, 2, 0.016666668F);
        MPStatistic.getInstance().Bullet.End();
        this.time = zombie.GameTime.getServerTimeMills();
    }

    public void update() {
        WorldSimulation.s_performance.worldSimulationUpdate.invokeAndMeasure(this, WorldSimulation::updateInternal);
    }

    private void updateInternal() {
        if (this.created) {
            this.updatePhysic(zombie.GameTime.instance.getRealworldSecondsSinceLastUpdate());
            this.collideVehicles.clear();
            int int0 = Bullet.getVehicleCount();
            int int1 = 0;

            while (int1 < int0) {
                MPStatistic.getInstance().Bullet.Start();
                int int2 = Bullet.getVehiclePhysics(int1, this.ff);
                MPStatistic.getInstance().Bullet.End();
                if (int2 <= 0) {
                    break;
                }

                int1 += int2;
                int int3 = 0;

                for (int int4 = 0; int4 < int2; int4++) {
                    int int5 = (int)this.ff[int3++];
                    float float0 = this.ff[int3++];
                    float float1 = this.ff[int3++];
                    float float2 = this.ff[int3++];
                    this.tempTransform.origin.set(float0, float1, float2);
                    float float3 = this.ff[int3++];
                    float float4 = this.ff[int3++];
                    float float5 = this.ff[int3++];
                    float float6 = this.ff[int3++];
                    this.javaxQuat4f.set(float3, float4, float5, float6);
                    this.tempTransform.setRotation(this.javaxQuat4f);
                    float float7 = this.ff[int3++];
                    float float8 = this.ff[int3++];
                    float float9 = this.ff[int3++];
                    this.tempVector3f.set(float7, float8, float9);
                    float float10 = this.ff[int3++];
                    float float11 = this.ff[int3++];
                    int int6 = (int)this.ff[int3++];

                    for (int int7 = 0; int7 < int6; int7++) {
                        this.wheelSteer[int7] = this.ff[int3++];
                        this.wheelRotation[int7] = this.ff[int3++];
                        this.wheelSkidInfo[int7] = this.ff[int3++];
                        this.wheelSuspensionLength[int7] = this.ff[int3++];
                    }

                    int int8 = (int)(
                        float0 * 100.0F + float1 * 100.0F + float2 * 100.0F + float3 * 100.0F + float4 * 100.0F + float5 * 100.0F + float6 * 100.0F
                    );
                    BaseVehicle baseVehicle0 = VehicleManager.instance.getVehicleByID((short)int5);
                    if (baseVehicle0 != null
                        && (
                            !GameClient.bClient
                                || !baseVehicle0.isNetPlayerAuthorization(BaseVehicle.Authorization.Remote)
                                    && !baseVehicle0.isNetPlayerAuthorization(BaseVehicle.Authorization.RemoteCollide)
                        )) {
                        if (baseVehicle0.VehicleID == int5 && float11 > 0.5F) {
                            this.collideVehicles.add(baseVehicle0);
                            baseVehicle0.authSimulationHash = int8;
                        }

                        if (GameClient.bClient && baseVehicle0.isNetPlayerAuthorization(BaseVehicle.Authorization.LocalCollide)) {
                            if (baseVehicle0.authSimulationHash != int8) {
                                baseVehicle0.authSimulationTime = System.currentTimeMillis();
                                baseVehicle0.authSimulationHash = int8;
                            }

                            if (System.currentTimeMillis() - baseVehicle0.authSimulationTime > 1000L) {
                                VehicleManager.instance.sendCollide(baseVehicle0, baseVehicle0.getDriver(), false);
                                baseVehicle0.authSimulationTime = 0L;
                            }
                        }

                        if (!baseVehicle0.isNetPlayerAuthorization(BaseVehicle.Authorization.Remote)
                            || !baseVehicle0.isNetPlayerAuthorization(BaseVehicle.Authorization.RemoteCollide)) {
                            if (GameClient.bClient && baseVehicle0.isNetPlayerAuthorization(BaseVehicle.Authorization.Server)) {
                                baseVehicle0.jniSpeed = 0.0F;
                            } else {
                                baseVehicle0.jniSpeed = float10;
                            }
                        }

                        if (!GameClient.bClient
                            || !baseVehicle0.isNetPlayerAuthorization(BaseVehicle.Authorization.Server)
                                && !baseVehicle0.isNetPlayerAuthorization(BaseVehicle.Authorization.Remote)
                                && !baseVehicle0.isNetPlayerAuthorization(BaseVehicle.Authorization.RemoteCollide)) {
                            if (this.compareTransform(this.tempTransform, baseVehicle0.getPoly().t)) {
                                baseVehicle0.polyDirty = true;
                            }

                            baseVehicle0.jniTransform.set(this.tempTransform);
                            baseVehicle0.jniLinearVelocity.set(this.tempVector3f);
                            baseVehicle0.jniIsCollide = float11 > 0.5F;

                            for (int int9 = 0; int9 < int6; int9++) {
                                baseVehicle0.wheelInfo[int9].steering = this.wheelSteer[int9];
                                baseVehicle0.wheelInfo[int9].rotation = this.wheelRotation[int9];
                                baseVehicle0.wheelInfo[int9].skidInfo = this.wheelSkidInfo[int9];
                                baseVehicle0.wheelInfo[int9].suspensionLength = this.wheelSuspensionLength[int9];
                            }
                        }
                    }
                }
            }

            if (GameClient.bClient) {
                IsoPlayer isoPlayer = IsoPlayer.players[IsoPlayer.getPlayerIndex()];
                if (isoPlayer != null) {
                    BaseVehicle baseVehicle1 = isoPlayer.getVehicle();
                    if (baseVehicle1 != null && baseVehicle1.isNetPlayerId(isoPlayer.getOnlineID()) && this.collideVehicles.contains(baseVehicle1)) {
                        for (BaseVehicle baseVehicle2 : this.collideVehicles) {
                            if (baseVehicle2.DistTo(baseVehicle1) < 8.0F && baseVehicle2.isNetPlayerAuthorization(BaseVehicle.Authorization.Server)) {
                                VehicleManager.instance.sendCollide(baseVehicle2, isoPlayer, true);
                                baseVehicle2.authorizationClientCollide(isoPlayer);
                            }
                        }
                    }
                }
            }

            MPStatistic.getInstance().Bullet.Start();
            int int10 = Bullet.getObjectPhysics(this.ff);
            MPStatistic.getInstance().Bullet.End();
            int int11 = 0;

            for (int int12 = 0; int12 < int10; int12++) {
                int int13 = (int)this.ff[int11++];
                float float12 = this.ff[int11++];
                float float13 = this.ff[int11++];
                float float14 = this.ff[int11++];
                float12 += this.offsetX;
                float14 += this.offsetY;
                IsoMovingObject isoMovingObject = (IsoMovingObject)this.physicsObjectMap.get(int13);
                if (isoMovingObject != null) {
                    isoMovingObject.removeFromSquare();
                    isoMovingObject.setX(float12 + 0.18F);
                    isoMovingObject.setY(float14);
                    isoMovingObject.setZ(Math.max(0.0F, float13 / 3.0F / 0.82F));
                    isoMovingObject.setCurrent(
                        IsoWorld.instance
                            .getCell()
                            .getGridSquare((double)isoMovingObject.getX(), (double)isoMovingObject.getY(), (double)isoMovingObject.getZ())
                    );
                }
            }
        }
    }

    private boolean compareTransform(Transform transform1, Transform transform0) {
        if (!(Math.abs(transform1.origin.x - transform0.origin.x) > 0.01F)
            && !(Math.abs(transform1.origin.z - transform0.origin.z) > 0.01F)
            && (int)transform1.origin.y == (int)transform0.origin.y) {
            byte _byte = 2;
            transform1.basis.getColumn(_byte, this.tempVector3f_2);
            float float0 = this.tempVector3f_2.x;
            float float1 = this.tempVector3f_2.z;
            transform0.basis.getColumn(_byte, this.tempVector3f_2);
            float float2 = this.tempVector3f_2.x;
            float float3 = this.tempVector3f_2.z;
            return Math.abs(float0 - float2) > 0.001F || Math.abs(float1 - float3) > 0.001F;
        } else {
            return true;
        }
    }

    public int setOwnVehiclePhysics(int _int, float[] _float) {
        return Bullet.setOwnVehiclePhysics(_int, _float);
    }

    public void activateChunkMap(int playerIndex) {
        this.create();
        IsoChunkMap isoChunkMap = IsoWorld.instance.CurrentCell.ChunkMap[playerIndex];
        if (!GameServer.bServer) {
            Bullet.activateChunkMap(playerIndex, isoChunkMap.getWorldXMin(), isoChunkMap.getWorldYMin(), IsoChunkMap.ChunkGridWidth);
        }
    }

    public void deactivateChunkMap(int playerIndex) {
        if (this.created) {
            Bullet.deactivateChunkMap(playerIndex);
        }
    }

    public void scrollGroundLeft(int playerIndex) {
        if (this.created) {
            Bullet.scrollChunkMapLeft(playerIndex);
        }
    }

    public void scrollGroundRight(int playerIndex) {
        if (this.created) {
            Bullet.scrollChunkMapRight(playerIndex);
        }
    }

    public void scrollGroundUp(int playerIndex) {
        if (this.created) {
            Bullet.scrollChunkMapUp(playerIndex);
        }
    }

    public void scrollGroundDown(int playerIndex) {
        if (this.created) {
            Bullet.scrollChunkMapDown(playerIndex);
        }
    }

    public static TextureDraw.GenericDrawer getDrawer(int playerIndex) {
        PhysicsDebugRenderer physicsDebugRenderer = PhysicsDebugRenderer.alloc();
        physicsDebugRenderer.init(IsoPlayer.players[playerIndex]);
        return physicsDebugRenderer;
    }

    private static class s_performance {
        static final PerformanceProfileProbe worldSimulationUpdate = new PerformanceProfileProbe("WorldSimulation.update");
    }
}
